import {asyncRoutes, constantRoutes} from '@/router'
import {anyMatch} from "@/utils/ant-matcher"

/**
 * determine whether the `route` is included in the `menuPatterns` under the ant matching rules
 */
function hasPermission(menuPatterns, route) {
    // treatment the `*` route specially
    return route.path === '*' ? true : anyMatch(menuPatterns, route.path)
}

/**
 * Filter asynchronous routing tables by recursion
 */
export function filterAsyncRoutes(routes, menuPatterns) {
    const res = []

    routes.forEach(route => {
        const tmp = {...route}
        if (hasPermission(menuPatterns, tmp)) {
            if (tmp.children) {
                tmp.children = filterAsyncRoutes(tmp.children, menuPatterns)
            }
            res.push(tmp)
        }
    })

    return res
}

const state = {
    // the routes that current user can access, including the `constantRoutes` and the `addRoutes`
    routes: [],
    // generated by the user's menus access control limit dynamically
    addRoutes: []
}

const mutations = {
    SET_ROUTES: (state, routes) => {
        state.addRoutes = routes
        state.routes = constantRoutes.concat(routes)
    }
}

const actions = {
    generateRoutes({commit}, menuPatterns) {
        return new Promise(resolve => {
            let accessibleRoutes = []
            if (menuPatterns.length === 0) {
                /*
                 * ensure the `*` route generated for the 404 not found page redirection,
                 * must ensure the `*` route is the last one in the `asyncRoutes`
                 */
                accessibleRoutes.push(asyncRoutes[asyncRoutes.length - 1])
            } else {
                // filter out routes in `asyncRoutes` that match any ant matching rules in `menuPatterns`
                accessibleRoutes = filterAsyncRoutes(asyncRoutes, menuPatterns);
            }

            commit('SET_ROUTES', accessibleRoutes)
            resolve(accessibleRoutes)
        })
    }
}

export default {
    namespaced: true,
    state,
    mutations,
    actions
}
